/* 
抽象工厂 和 具体工厂的区别
抽象工厂不提供任何实例方法 只用来 约定住这台手机的基本组成 
具体工厂用来执行 具体的逻辑

*/

// Boss——AbstractFactory
class MobilePhoneFactory {
    // 提供操作系统的接口
    createOS(){
        throw new Error("抽象工厂方法不允许直接调用，你需要将我重写！");
    }
    // 提供硬件的接口
    createHardWare(){
        throw new Error("抽象工厂方法不允许直接调用，你需要将我重写！");
    }
}

// 具体工厂 ConcreteFactory 继承自抽象工厂
class FakeStarFactory extends MobilePhoneFactory {
    createOS() {
        // 提供安卓系统实例
        return new AndroidOS() // 生成具体的操作系统
    }
    createHardWare() {
        // 提供高通硬件实例
        return new QualcommHardWare() // 生成硬件实例
    }
}



/* 
抽象产品类 和 具体产品类 的关系
具体产品类往往不会孤立存在，不同的具体产品类往往有着共同的功能，比如安卓系统类和苹果系统类，它们都是操作系统，都有着可以操控手机硬件系统这样一个最基本的功能。
因此我们可以用一个抽象产品（AbstractProduct）类来声明这一类产品应该具有的基本功能
*/

// 定义操作系统这类产品的抽象产品类  AbstractProduct
class OS {
    controlHardWare() {
        throw new Error('抽象产品方法不允许直接调用，你需要将我重写！');
    }
}

// 定义具体操作系统的具体产品类  ConcreteProduct
class AndroidOS extends OS {
    controlHardWare() {
        console.log('我会用安卓的方式去操作硬件')
    }
}

class AppleOS extends OS {
    controlHardWare() {
        console.log('我会用🍎的方式去操作硬件')
    }
}


// 定义手机硬件这类产品的抽象产品类
class HardWare {
    // 手机硬件的共性方法，这里提取了“根据命令运转”这个共性
    operateByOrder() {
        throw new Error('抽象产品方法不允许直接调用，你需要将我重写！');
    }
}

// 定义具体硬件的具体产品类
class QualcommHardWare extends HardWare {
    operateByOrder() {
        console.log('我会用高通的方式去运转')
    }
}

class MiWare extends HardWare {
    operateByOrder() {
        console.log('我会用小米的方式去运转')
    }
}



// 生产一台手机
// 这是我的手机
const myPhone = new FakeStarFactory()
// 让它拥有操作系统
const myOS = myPhone.createOS()
// 让它拥有硬件
const myHardWare = myPhone.createHardWare()
// 启动操作系统(输出‘我会用安卓的方式去操作硬件’)
myOS.controlHardWare()
// 唤醒硬件(输出‘我会用高通的方式去运转’)
myHardWare.operateByOrder()

// 这样生产无数台手机就有分别修改各自的 具体工厂  具体产品  且互不影响

// -----------------------------------------------------------------------------------------------------------------------

// 对于简单工厂函数 改装成抽象工厂
// 公司每个员工由 个人信息 和 工作职责 组成
class Personnel{
    // 提供操作系统的接口
    createUserInfo(){
        throw new Error("抽象工厂方法不允许直接调用，你需要将我重写！");
    }
    // 提供硬件的接口
    createWorkDetail(){
        throw new Error("抽象工厂方法不允许直接调用，你需要将我重写！");
    }
}

// 具体工厂 管理员工厂
class AdminFactory extends Personnel {
    // 创建信息资料
    createUserInfo(name , age , sex , tel , email ){
        return new AdminUserInfo(name , age , sex , tel , email)
    }
    // 创建工作职责
    createWorkDetail(workArray){
        return new AdminWorkDetail(workArray)
    }
}

// 抽象产品
class UserInfo {
    getinformation(){
        throw new Error("不允许调用")
    }
}
// 具体产品
class AdminUserInfo extends UserInfo {
    constructor(name, age, sex, tel, email) {
        super();
        this.name = name;
        this.age = age;
        this.sex = sex;
        this.tel = tel;
        this.email = email;
    }
    getinformation(){
        console.log(`管理员信息：姓名 - ${this.name}, 年龄 - ${this.age}, 性别 - ${this.sex}, 电话 - ${this.tel}, 邮箱 - ${this.email}`);
    }
}


// 抽象产品 - 工作职责
class WorkDetail {
    // 工作职责相关的抽象方法
    getWorkDetail(){
        throw new Error("不允许调用")
    }
}

// 具体产品 - 管理员编码工作职责
class AdminWorkDetail extends WorkDetail {
    constructor(workArray) {
        super();
        this.workArray = workArray;
    }
    getWorkDetail() {
        console.log('管理员的编码工作职责' , this.workArray);
    }
}



const testAdmin = new AdminFactory() // 创建管理员
const testUserinfo = testAdmin.createUserInfo('张三', 30,'男', '123456789', 'zhangsan@example.com'); // 创建管理员用户信息
const adminWork = testAdmin.createWorkDetail(['manage', 'coder']);  // 分配工作职责
testUserinfo.getinformation()  // 输出用户信息
adminWork.getWorkDetail()  // 输出工作职责